import RNFetchBlob from 'react-native-fetch-blob';
import _ from 'lodash';
import util from '../util';
import request from '../util/request';
import localStorage from '../util/storage';
import mqtt from '../util/mqtt';
import uploadFile from '../util/upload';

const uuidV4 = require('uuid/v4');

const ROLES = {
  0: 'vip',
  1: 'vip',
  2: 'teacher',
};
class MqttStore {
  // 监听对象
  @observable chatRoomHistory = [];
  // 语音消息
  @observable voicesHistory = [];
  // 用户信息
  @observable user = {
    roleflag: 0, // 默认为普通用户
  };
  // 非监听对象
  chatListMap = observable.map();
  client = null;
  roomID = 0;
  page = 0;
  index = 1;
  constructor() {
    // 从缓存中恢复聊天记录
    this._restoreChaltFromStorage();
  }
  // 恢复聊天记录
  _restoreChaltFromStorage = async () => {
    const res = await localStorage('room').get();
    return res;
  }
  // 获取用户图片上传文件权限
  _getResourceToken = async (prefix = 'jpg') => await request.post('/account/resource',
    { name: `chat_resource${uuidV4()}`, prefix, stage: 'chat' });
  // 用户角色
  @computed get role() {
    const user = toJS(this.user);
    return ROLES[user.roleflag];
  }
  // 获取课程的语音
  @computed get voiceItems() {
    const voiceArr = toJS(this.voicesHistory);
    return _.filter(voiceArr, { isTeacher: true, course: true });
  }
  // 聊天内容
  @computed get chatItems() {
    const historyArr = toJS(this.chatRoomHistory);
    const chatItems = toJS([...this.chatListMap.values()]);
    let items = _.concat(historyArr, chatItems);
    items = _.uniqBy(items, 'key');
    return _.filter(items, { course: false });
  }
  // 老师课程列表
  @computed get teacherItems() {
    const historyArr = toJS(this.chatRoomHistory);
    const chatItems = toJS([...this.chatListMap.values()]);
    let items = _.concat(historyArr, chatItems);
    items = _.uniqBy(items, 'key');
    return _.filter(items, { isTeacher: true, course: true });
  }
  // 断开连接
  _disconnect() {
    if (this.client) {
      this.client.end();
      this.user = {}; // 清空用户信息
      this.chatListMap.clear(); // 移除之前课程的聊天内容
      this.chatRoomHistory.clear(); // 移除聊天历史记录
      this.roomID = 0;
      this.index = 1;
    }
  }
  // mqtt 连接
  _init(roomCode, user) {
    this.roomID = roomCode;
    if (user && user.clientId) {
      this._joinRoom(roomCode);
      this.user = user;
    }
    this._getChatHistory({ roomCode });
    this._getChatVoice({ roomCode });
  }
  _connect(id) {
    const { clientId, loginName, token } = this.user;
    const params = {
      clientId,
      clean: true,
      username: loginName,
      password: token,
      reconnectPeriod: 3000, // 重连
    };
    this.client = mqtt.connect('ws://120.76.204.187:3001', params);
    this.client.on('connect', () => {
      const topic = {};
      topic[id] = 1;
      this.client.subscribe(topic);
    });
    this.client.on('reconnect', () => {
      const topic = {};
      topic[id] = 1;
      this.client.subscribe(topic);
    });
    // 接收消息
    this.client.on('message', (topic, message) => {
      this._onReceiveMessage(topic, message);
    });
    // 连接失败
    this.client.on('error', (error) => {
      this._onMqttError(error);
    });
  }
  // 发送图片
  _sendImg(path, text = '', course = false) {
    const key = this._preMessage(course);
    this._getResourceToken().then((res) => {
      if (res && res.code === 200) {
        const body = [
          { name: 'token', data: res.result.token },
          { name: 'key', data: res.result.filename },
          { name: 'file', filename: 'chat_img', data: RNFetchBlob.wrap(path) },
        ];
        uploadFile('http://up-z2.qiniu.com', body, () => {}, (result) => {
          const url = `http://chat.static.zazn.cn/${result.key}`;
          this._sendMessage(text || '$$', { source: 'img', url, preKey: key }, course);
        }, () => {
          this._removeMessage(key);
        });
      } else {
        this._removeMessage(key);
      }
    });
  }
  // 发送声音
  _sendVoice(path, text = '', key, course = false) {
    this._getResourceToken('aac').then((res) => {
      if (res && res.code === 200) {
        const body = [
          { name: 'token', data: res.result.token },
          { name: 'key', data: res.result.filename },
          { name: 'file', filename: 'chat_voice', data: RNFetchBlob.wrap(path) },
        ];
        uploadFile('http://up-z2.qiniu.com', body, () => {}, (result) => {
          const url = `http://chat.static.zazn.cn/${result.key}`;
          this._sendMessage(text || '$$', { source: 'audio', url, preKey: key }, course);
        }, () => {
          this._removeMessage(key);
        });
      } else {
        this._removeMessage(key);
      }
    });
  }
  _preMessage(course = false) {
    const { avatar } = this.user;
    const key = `pre_${uuidV4()}`;
    const msg = {
      key,
      course,
      isTeacher: true,
      preMessage: true,
      avatar: avatar ? `${avatar}?imageMogr2/thumbnail/200x200/interlace/1` : '',
      reverse: true,
    };
    this.chatListMap.set(key, msg);
    return key;
  }
  // 更新消息的阅读状态
  _updateVoiceStatus(id) {
    const historyArr = toJS(this.chatRoomHistory);
    const voice = _.find(historyArr, { key: id }) || {};
    voice.visite = true;
    this.chatRoomHistory = historyArr;
  }
  // 撤销消息
  async _cancleMsg(uuid) {
    const response = await request.post('/message/delete', { uuid });
    if (response && response.code === 200) {
      this._removeMessage(uuid);
    }
    return response;
  }
  // 删除消息
  _removeMessage(key) {
    this.chatListMap.delete(key);
    const historyArr = toJS(this.chatRoomHistory);
    _.remove(historyArr, { key });
    this.chatRoomHistory = historyArr;
  }
  // 发送消息
  _sendMessage(msg, extra = {}, course = false) {
    const { nickName, clientId, avatar, roleflag } = this.user;
    const msgObj = {
      type: 'text_standard',  // 没有遵守 mqqt 的协议 意义不大 后端没有处理资源文件
      track: -1,   // 一般不需要跟踪的消息默认为－1 ，其他需填入跟踪号
      mode: 0, // 0 为群聊，1为私聊
      msg,
      course,
      nickName,
      roleflag,
      isTeacher: true,
      avatar,
      from: clientId,
      ...extra,
    };
    this.client.publish(this.roomID, JSON.stringify(msgObj), { qos: 1, retain: false });
  }
  // 格式化数据
  _formateData = (item) => {
    const { clientId } = this.user;
    const message = item;
    if (!message.uuid) {
      message.key = uuidV4();
    } else {
      message.key = message.uuid;
    }
    message.msg = _.replace(message.msg, '$$', '');
    message.avatar = util.isImg(message.avatar) ? `${message.avatar}?imageMogr2/thumbnail/200x200/interlace/1` : '';
    message.reverse = clientId === message.from;
    return message;
  }
  // 接收消息
  _onReceiveMessage(topic, message) {
    // 接到的数据是 buffer 所以需要转一把
    const msgStr = message.toString();
    try {
      const msg = JSON.parse(msgStr);
      const msgObj = this._formateData(msg);
      let mapKey = '';
      if (msg.preKey) {
        mapKey = msgObj.preKey;
      } else {
        mapKey = msgObj.key;
      }
      this.chatListMap.set(mapKey, msgObj);
    } catch (error) {
      console.log(error);
    }
  }
  // 连接错误
  _onMqttError(error) {
    console.log(error);
  }
  // 加入房间 获得订阅的权限id
  async _joinRoom(roomCode) {
    const { clientId, token } = this.user;
    const response = await request.put('/chat/room/joinWithCode', { roomCode, clientId, token });
    if (response && response.code === 200) {
      this._connect(roomCode);
    }
    return response;
  }
  // 获取全部的语音
  async _getChatVoice({ roomCode, page = 1, items = 500, view = 0, mode = 0 }) {
    const response = await request.put('/chat/history', {
      roomCode,
      mode,
      items,
      view,
      page,
      source: 'audio',
    });
    if (response && response.code === 200) {
      const { dataList } = response.result;
      const voices = _.map(dataList, (item) => {
        const {
          uuid, isTeacher, course, url } = item;
        return {
          key: uuid,
          url,
          reverse: false,
          isTeacher: isTeacher === 'true',
          course: course === 'true',
        };
      });
      this.voicesHistory = voices;
    }
  }
  // 获取聊天记录
  async _getChatHistory({ roomCode, page = 1, items = 30, view = 0, mode = 0 }) {
    const response = await request.put('/chat/history', {
      roomCode,
      mode,
      items,
      view,
      page,
    });
    if (response && response.code === 200) {
      const { dataList, total } = response.result;
      this.page = total;
      const history = _.map(dataList, (item) => {
        const {
          uuid, msg, nickName,
          isTeacher, course, type, posted, avatar, source, url,
        } = item;
        return {
          key: uuid,
          msg: _.replace(msg, '$$', ''),
          source,
          url,
          nickName,
          type,
          avatar: util.isImg(avatar) ? `${avatar}?imageMogr2/thumbnail/200x200/interlace/1` : '',
          posted,
          reverse: false,
          isTeacher: isTeacher === 'true',
          course: course === 'true',
        };
      });
      this.chatRoomHistory = history;
    }
  }
  // 下拉获取新的聊天记录
  async _pullChatHistory() {
    let pageTotal = 0;
    let response = null;
    const roomCode = this.roomID;
    if (this.index < this.page) {
      this.index += 1;
      response = await request.put('/chat/history', {
        roomCode,
        mode: 0,
        items: 30,
        view: 0,
        page: this.index,
      });
      if (response && response.code === 200) {
        const { dataList, total } = response.result;
        const history = _.map(dataList, (item) => {
          const {
            uuid, msg, nickName, from, isTeacher,
            course, type, posted, avatar, source, url } = item;
          return {
            key: uuid,
            msg: _.replace(msg, '$$', ''),
            source,
            url,
            nickName,
            type,
            avatar: util.isImg(avatar) ? `${avatar}?imageMogr2/thumbnail/200x200/interlace/1` : '',
            posted,
            reverse: false,
            isTeacher: isTeacher === 'true',
            course: course === 'true',
          };
        });
        const oldArr = toJS(this.chatRoomHistory);
        this.chatRoomHistory = _.concat(oldArr, history);
        pageTotal = total;
      }
    }
    return pageTotal;
  }
}
export default new MqttStore();
